// Fill out your copyright notice in the Description page of Project Settings.


#include "HotPakerFileLib.h"
#include "Misc/Paths.h"
#include "Misc/App.h"
#include "AssetRegistryModule.h"

#ifdef __DEVELOPER_MODE__
#include "Interfaces/ITargetPlatformManagerModule.h"
#include "Interfaces/ITargetPlatform.h"
#endif


const FName UHotPakerFileLib::AssetRegistryName(TEXT("AssetRegistry"));

FString UHotPakerFileLib::GetProjectName()
{
	return FApp::GetProjectName();
}

FString UHotPakerFileLib::GetUnrealPakBinary()
{
	FString PakBinaryPath;
#if PLATFORM_WINDOWS
	PakBinaryPath = FPaths::Combine(
		FPaths::ConvertRelativePathToFull(FPaths::EngineDir()),
		TEXT("Binaries"),
#if PLATFORM_64BITS	
		TEXT("Win64"),
#else
		TEXT("Win32"),
#endif
		TEXT("UnrealPak.exe")
	);
#endif

#if PLATFORM_MAC
	PakBinaryPath = FPaths::Combine(
		FPaths::ConvertRelativePathToFull(FPaths::EngineDir()),
		TEXT("Binaries"),
		TEXT("Mac"),
		TEXT("UnrealPak")
	);
#endif

	FPaths::MakeStandardFilename(PakBinaryPath);
	return FPaths::ConvertRelativePathToFull(PakBinaryPath);
}

FString UHotPakerFileLib::GetUE4CmdBinary()
{
	FString CmdBinaryPath;
#if PLATFORM_WINDOWS
	CmdBinaryPath = FPaths::Combine(
		FPaths::ConvertRelativePathToFull(FPaths::EngineDir()),
		TEXT("Binaries"),
#if PLATFORM_64BITS	
		TEXT("Win64"),
#else
		TEXT("Win32"),
#endif
		TEXT("UE4Editor-Cmd.exe")
	);
#endif
#if PLATFORM_MAC
	CmdBinaryPath = FPaths::Combine(
		FPaths::ConvertRelativePathToFull(FPaths::EngineDir()),
		TEXT("Binaries"),
		TEXT("Mac"),
		TEXT("UE4Editor-Cmd")
	);
#endif
	FPaths::MakeStandardFilename(CmdBinaryPath);
	return FPaths::ConvertRelativePathToFull(CmdBinaryPath);
}

TArray<FString> UHotPakerFileLib::GetAllPlatforms()
{
#ifdef __DEVELOPER_MODE__
	TArray<ITargetPlatform*> Platforms = GetTargetPlatformManager()->GetTargetPlatforms();
	TArray<FString> result;

	for (const auto& PlatformItem : Platforms)
	{
		result.Add(PlatformItem->PlatformName());
	}

#else
	TArray<FString> result = {
		"AllDesktop",
		"MacClient",
		"MacNoEditor",
		"MacServer",
		"Mac",
		"WindowsClient",
		"WindowsNoEditor",
		"WindowsServer",
		"Windows",
		"Android",
		"Android_ASTC",
		"Android_ATC",
		"Android_DXT",
		"Android_ETC1",
		"Android_ETC1a",
		"Android_ETC2",
		"Android_PVRTC",
		"AndroidClient",
		"Android_ASTCClient",
		"Android_ATCClient",
		"Android_DXTClient",
		"Android_ETC1Client",
		"Android_ETC1aClient",
		"Android_ETC2Client",
		"Android_PVRTCClient",
		"Android_Multi",
		"Android_MultiClient",
		"HTML5",
		"IOSClient",
		"IOS",
		"TVOSClient",
		"TVOS",
		"LinuxClient",
		"LinuxNoEditor",
		"LinuxServer",
		"Linux",
		"Lumin",
		"LuminClient"
	};

#endif
	return result;
}

FString UHotPakerFileLib::ConverPackagePathToFullPath(FString PackagePath)
{
	if (PackagePath.StartsWith(TEXT("/Game")))
	{
		PackagePath.RemoveAt(0, 6);
		return FPaths::Combine(FPaths::ConvertRelativePathToFull(FPaths::GameContentDir()), PackagePath);
	}
	if (PackagePath.StartsWith(TEXT("/Engine")))
	{
		PackagePath.RemoveAt(0, 8);
		return FPaths::Combine(FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir()), PackagePath);
	}
	return FString();
}

FString UHotPakerFileLib::ConverFullPathToPackagePath(FString FullPath)
{
	if (FullPath.Contains(FPaths::ConvertRelativePathToFull(FPaths::GameContentDir())))
	{
		return FullPath.Replace(*FPaths::ConvertRelativePathToFull(FPaths::GameContentDir()), TEXT("/Game/"));
	}
	if (FullPath.StartsWith(FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir())))
	{
		return FullPath.Replace(*FPaths::ConvertRelativePathToFull(FPaths::EngineContentDir()), TEXT("/Engine/"));
	}
	return FString();
}

TArray<FName> UHotPakerFileLib::GetAssetDependencies(const FName& InPackageName)
{
	TArray<FName> TotalDependenceAssets;
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
	AssetRegistryModule.GetDependencies(InPackageName, TotalDependenceAssets, EAssetRegistryDependencyType::Packages);
	TArray<FName> DependenceAssets;
	for (auto DependenceAsset : TotalDependenceAssets)
		if (!DependenceAsset.ToString().StartsWith(TEXT("/Script")))
			DependenceAssets.Add(DependenceAsset);
	return DependenceAssets;
}

void UHotPakerFileLib::GetAssetAllDependencies(const FName& InPackageName, TArray<FName>& OutDependencies)
{
	if (OutDependencies.Contains(InPackageName))
		return;

	OutDependencies.Add(InPackageName);

	TArray<FName> AssetDependencies = GetAssetDependencies(InPackageName);

	for (auto AssetDependence : AssetDependencies)
	{
		if (!OutDependencies.Contains(AssetDependence))
		{
			OutDependencies.Add(AssetDependence);
			GetAssetAllDependencies(AssetDependence, OutDependencies);
		}
	}
}

void UHotPakerFileLib::GetAssetsAllDependencies(const TArray<FName>& InPackageNames, TArray<FName>& OutDependencies)
{
	for (auto PackageName : InPackageNames)
		GetAssetAllDependencies(PackageName, OutDependencies);
}

bool UHotPakerFileLib::ConverPackageNameToSavePath(const FName& InPackageName, const FString& InSavePath, const FString& InPlatform, FString& OutSavePath)
{
	FString PackageName = InPackageName.ToString().Append(TEXT(".uasset"));
	if (PackageName.StartsWith(TEXT("/Game")))
	{
		PackageName.RemoveAt(0, 6);
		OutSavePath = FPaths::Combine(InSavePath, InPlatform, GetProjectName(), TEXT("Content"), PackageName);
		return true;
	}
	if (PackageName.StartsWith(TEXT("/Engine")))
	{
		PackageName.RemoveAt(0, 1);
		OutSavePath = FPaths::Combine(InSavePath, InPlatform, PackageName);
		return true;
	}
	return false;
}

bool UHotPakerFileLib::GetAssetDataByPackageName(const FName& InPackageName, FAssetData& AssetData)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
	TArray<FAssetData> AssetDatas;
	if (AssetRegistryModule.Get().GetAssetsByPackageName(InPackageName, AssetDatas) && AssetDatas.Num() > 0 && !AssetDatas[0].IsRedirector())
	{
		AssetData = AssetDatas[0];
		return true;
	}
	return false;
}

bool UHotPakerFileLib::GetAssetDatasByPackageNames(const TArray<FName>& InPackageNames, TArray<FAssetData>& OutAssetDatas)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
	for (auto PackageName : InPackageNames)
	{
		TArray<FAssetData> AssetDatas;
		if (AssetRegistryModule.Get().GetAssetsByPackageName(PackageName, AssetDatas) && AssetDatas.Num() > 0 && !AssetDatas[0].IsRedirector())
			OutAssetDatas.AddUnique(AssetDatas[0]);
	}
	if (OutAssetDatas.Num() == InPackageNames.Num())
		return true;
	return false;
}

const FAssetPackageData* UHotPakerFileLib::GetAssetPackageDataByPackageName(const FName& InPackageName)
{
	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
	return AssetRegistryModule.Get().GetAssetPackageData(InPackageName);
}

